#include <pthread.h>
#include <stdlib.h>
#include "stack.h"
#include "string.h"
#include "stdio.h"



int push (Stack *stk, char *str) {
	Node *node = (Node *)malloc(sizeof(Node));
	if (node == NULL){
		return -1;
	}
	node->str = (char *)malloc(sizeof(char)*(strlen(str) + 1));
	if (node->str == NULL){
		free(node);
		return -1;
	}
	strcpy(node->str, str);
	pthread_mutex_lock((pthread_mutex_t *)stk->mutex);
	if (stk->head == NULL) {
		node->next = NULL;
	} else {
		node->next = stk->head;
	}
	stk->head = node;
	pthread_mutex_unlock((pthread_mutex_t *)stk->mutex);

	return 1;
}

void pop(Stack *stk) {
	Node *tmp;
	pthread_mutex_lock((pthread_mutex_t *)stk->mutex);
	if (stk->head != NULL) {
		tmp = stk->head->next;
		free(stk->head->str);
		free(stk->head);
		stk->head = tmp;
	}
	pthread_mutex_unlock((pthread_mutex_t *)stk->mutex);
	return;
}

int top(Stack *stk, char *buf)
{
	int retVal;

	pthread_mutex_lock((pthread_mutex_t *)stk->mutex);
	if (stk->head != NULL) {
		strcpy(buf, stk->head->str);
		retVal = 1;
	} else {
		retVal = 0;
	}
	pthread_mutex_unlock((pthread_mutex_t *)stk->mutex);

	return retVal;
}

void show(Stack *stk){
	Node *p;

	if (stk->head == NULL) return;

	p = stk->head;
	while (p != NULL){
		if (p->str != NULL){
			printf("%s", p->str);
		}
		p = p->next;
	}
	return;
}

void freeStack(Stack *stk) {
	Node *tmp;
	while (stk->head != NULL) {
		tmp = stk->head->next;
		free(stk->head->str);
		free(stk->head);
		if (tmp == NULL) {
			break;
		} else {
			stk->head = tmp;
		}
	}
	stk = NULL;
}

//char *getUserInput() {
//	char *input = (char*)malloc(sizeof(char)*DEFAULT_USER_INPUT_LENGTH);
//	if (NULL==input) {
//		return NULL;
//	}
//	if (fgets(input, DEFAULT_USER_INPUT_LENGTH, stdin) == NULL) {
//		fprintf(stdout, "Error: EOF or IO error occured");
//		free(input);
//		return NULL;
//	}
//	return input;
//}
//
//int execFunc(char *input, Stack *stk){
//	char buf[1024];
//	char *func;
//	int end = 0, i, begin;
//	/* find the end of the command */
//	while (input[end] != '\n' && input[end] != '\0' && input[end] != '\t' && input[end] != ' ') {
//		end++;
//	}
//	/* create a string out of the command */
//	func = (char *)malloc(sizeof(char)*(end + 1));
//	for (i = 0; i < end; i++) {
//		func[i] = input[i];
//	}
//	func[i] = '\0';
//	if (strcmp(func, (char *) "POP") == 0) {
//		pop(stk);
//		printf("popped\n");
//	}
//	else if (strcmp(func, (char *) "TOP") == 0) {
//		top(stk, buf);
//		printf("topped\n");
//	}
//	else if (strcmp(func, (char *) "PUSH") == 0) {
//		/* jump over white spaces to get to the string */
//		while ((input[end] != '\n' || input[end] != '\0') && (input[end] == '\t' || input[end] == ' ')) {
//			end++;
//		}
//		if	(input[--end] == '\0' || input[end] == '\n') {
//			fprintf(stdout, "Error: no string to push into stack");
//		} else {
//			/* find the beginning and end of the string */
//			begin = ++end;
//			while (input[end] != '\n' && input[end] != '\0') {
//				end++;
//			}
//			if (input[end] != '\n') {
//				fprintf (stdout, "Error: the input is not null terminated");
//			} else {
//				push(stk, &(input[begin]));
//				printf("pushed\n");
//			}
//		}
//	}
//	else if (strcmp(func, "show") == 0){
//		show(stk);
//	}
//	else if (strcmp(func, (char *) "QUIT") == 0) {
//		free(func);
//		return 0;
//	} else {
//		fprintf(stdout, "Error: invalid command");
//	}
//	free(func);
//	return 1;
//}

Stack *createStack() {
	Stack *stk = (Stack *)malloc(sizeof(Stack));
	if (stk == NULL){
		return NULL;
	}
	stk->mutex = (void *)malloc(sizeof(pthread_mutex_t));
	if (stk->mutex == NULL){
		free (stk);
		return NULL;
	}
	pthread_mutex_init((pthread_mutex_t *)stk->mutex, NULL);
	stk->head = NULL;
	return stk;
}

//int main() {
//	char *input;
//	int cont = 1;
//	Stack *stk = (Stack *)malloc(sizeof(Stack));
//	stk->head = NULL;
//	while (cont) {
//		input = getUserInput();
//		if (input != NULL) {
//			cont = execFunc(input, stk);
//			free(input);
//		}
//	}
//	freeStack(stk);
//}

//pthread_cond_t  condition_cond  = PTHREAD_COND_INITIALIZER;

//typedef struct ts_struct {
//	bool flag;
//} Ts_object;
//
//Bool test_set (Ts_object  *ts) {
//    if (ts->flag == FALSE) {
//        ts->flag = TRUE;
//        return FALSE;
//    }
//	else return TRUE;
//}
//
//void reset (Ts_object *ts) {
//	ts->flag = FALSE;
//}
//
//void lock_mutex (mutex * m) {
//	while (test_set((Ts_object *) m)) {
//		sleep((unsigned int) 2);
//	}
//}
//
//void unlock_mutex(mutex *m) {
//	reset((Ts_object *) m);
//}
